package com.wedo.web;/**
 * Created by cheng on 2018/5/8.
 */

import com.wedo.commons.wechat.*;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @author cheng
 * @create 2018/5/8
 */
@Controller
@RequestMapping("/wechat")
public class WechatPayController {
    @RequestMapping("/back")
    public String back(HttpServletRequest request, HttpServletResponse response) {
        String appid = Constants.APPID;     //公众号appId
        String appsecret = Constants.APPSECRET;       //公众号秘钥
        String code = request.getParameter("code");    //微信回传的参数
        String openId = "";
        String access_token = "";
        String URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appid+"&secret="+appsecret+"&code="+code+"&grant_type=authorization_code";
        JSONObject jsonObject = CommonUtil.httpsRequest(URL, "GET", null);
        if (null != jsonObject) {
            openId = jsonObject.getString("openid");    //得到openid
            //System.out.println("openId : " + openId) ;
            access_token = jsonObject.getString("access_token");
            //System.out.println("token : " + access_token) ;
        }
        request.getSession().setAttribute("openId", openId);

        //获取用户信息
        String nickname = "";
        String headimgurl = "";
        String userURL = "https://api.weixin.qq.com/sns/userinfo?access_token="+access_token+"&openid="+openId+"&lang=zh_CN";
        JSONObject userJson = CommonUtil.httpsRequest(userURL, "GET", null);
        if (null != jsonObject) {
            nickname = userJson.getString("nickname");
            headimgurl = userJson.getString("headimgurl");
        }
        request.setAttribute("nickname", nickname);
        request.setAttribute("headimgurl", headimgurl);

        return "/buy.jsp";    //跳转到支付页面
    }

    @RequestMapping("/pay")
    public void pay(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        JSONObject json = new JSONObject();

        //网页授权后获取传递的参数
        String money = "1";           //付款金额，分为单位
        String openid = (String)request.getSession().getAttribute("openId") ;   //上面获取的openid
        String spbill_create_ip = request.getParameter("ip");    //用户ip

        //商户相关资料
        String appId = Constants.APPID;              //公众号appId
        String appSecret = Constants.APPSECRET ;     //公众号秘钥
        String mch_id = Constants.MCH_ID;            //商户号
        String partnerKey = Constants.APIKEY ;       //商户API秘钥

        //用于获取随机数
        String currTime = TenpayUtil.getCurrTime() ;                       //获取当前时间yyyyMMddHHmmss
        String strTime = currTime.substring(8, currTime.length()) ;         //8位日期
        String strRandom = TenpayUtil.buildRandom(4) + "" ;                //四位随机数
        String strReq = strTime + strRandom ;                               //10位序列号,可以自行调整

        String out_trade_no = appId + Sha1Util.getTimeStamp() ;            //随机生成了一个订单号
        String nonce_str = strReq;     //随机数
        String body = "洗车下单";      //商品描述

        String attach = "有限公司";    //附加数据
        int total_fee = Integer.parseInt(money) ;      //总金额以分为单位，不带小数点

        //接收微信支付异步通知回调地址，可以判断会员是否支付成功，改变订单状态等：http://*/notifyServlet
        String notify_url = Constants.SERVER_ADDRESS+"/wt/notify";

        String trade_type = Constants.TRADE_TYPE;      //公众号支付

        //获取sign（统一下单接口签名）
        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appId);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("attach", attach);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("total_fee", money);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);
        packageParams.put("openid", openid);
        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appId, appSecret, partnerKey);
        String sign = reqHandler.createSign(packageParams);         //生成sign

        //组装统一下单接口携带参数（xml格式）
        StringBuilder xml = new StringBuilder("<xml>") ;
        setXmlKV(xml, "appid", appId) ;
        setXmlKV(xml, "mch_id", mch_id) ;
        setXmlKV(xml, "nonce_str", nonce_str) ;
        setXmlKV(xml, "body", body) ;
        setXmlKV(xml, "attach", attach) ;
        setXmlKV(xml, "out_trade_no", out_trade_no) ;
        setXmlKV(xml, "total_fee", total_fee+"") ;
        setXmlKV(xml, "spbill_create_ip", spbill_create_ip) ;
        setXmlKV(xml, "notify_url", notify_url) ;
        setXmlKV(xml, "trade_type", trade_type) ;
        setXmlKV(xml, "openid", openid) ;
        setXmlKV(xml, "sign", sign) ;
        xml.append("</xml>") ;
        System.out.println(xml.toString());

        //请求微信统一下单接口，成功后返回预支付交易会话标识prepay_id
        String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String prepay_id = "";
        try {
            prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml.toString());
            if(prepay_id.equals("")){
                request.setAttribute("ErrorMsg", "统一支付接口获取预支付订单出错");
                response.sendRedirect("error.jsp");
            }
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        //生成H5调起微信支付API相关参数（前端页面js的配置参数）
        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = Sha1Util.getTimeStamp();//当前时间的时间戳，秒数，注意不是毫秒
        finalpackage.put("appId", appId);//公众号appid
        finalpackage.put("timeStamp", timestamp);
        finalpackage.put("nonceStr", strReq); //随机数
        String packages = "prepay_id="+prepay_id ;//订单详情扩展字符串
        finalpackage.put("package", packages);
        finalpackage.put("signType", "MD5");//签名方式
        String finalSign = reqHandler.createSign(finalpackage);//支付签名

        json.put("appId", appId);
        json.put("timeStamp", timestamp);
        json.put("nonceStr", strReq);
        json.put("package", packages);
        json.put("sign", finalSign);
        json.put("signType", "MD5");
        JSONObject result = new JSONObject();
        result.put("code", 1) ;
        result.put("msg", "success") ;
        result.put("result", json) ;
        response.setContentType("text/html;charset=utf-8");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.getWriter().append(result.toString()) ;
    }

    @RequestMapping("/notify")
    public void notify(HttpServletRequest request, HttpServletResponse response){
        System.out.println("---notify");
        response.setContentType("text/xml;charset=UTF-8");
        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(Constants.APPID, Constants.APPSECRET, Constants.APIKEY);
        try {
            InputStream is = request.getInputStream();
            String resultStr = IOUtils.toString(is, "UTF-8");
            if("".equals(resultStr)){
                System.out.println("fail:result is null");
                response.getWriter().write("<xm><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数错误！]]></return_msg></xml>");
                return ;
            }
            //解析xml
            SortedMap<String, String> resultMap=(TreeMap)XMLUtil.doXMLParse(resultStr);
//                System.out.println(resultMap);
            String sign = resultMap.get("sign")+"";
            String sign2 = reqHandler.createSign(resultMap);
            String result_code=resultMap.get("result_code")+"";
            String return_code=resultMap.get("return_code")+"";
            if(sign.equals(sign2)){//校验签名，两者需要一致，防止别人绕过支付操作，不付钱直接调用你的业务，不然，哈哈，你老板会很开心的 233333.。。。
                if(return_code.equals("SUCCESS") && result_code.equals("SUCCESS")){
                    //业务逻辑(先判断数据库中订单号是否存在，并且订单状态为未支付状态)
                    try {
                        //resultMap.put("openid", request.getSession().getAttribute("openid"));


                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    //request.setAttribute("out_trade_no", out_trade_no);
                    //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                    response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
                }else{
                    response.getWriter().write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[交易失败]]></return_msg></xml>");
                }
            }else{
                //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                response.getWriter().write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名校验失败]]></return_msg></xml>");
            }
            response.getWriter().flush();
            response.getWriter().close();
            return;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static StringBuilder setXmlKV(StringBuilder sb,String Key,String value){
        sb.append("<");
        sb.append(Key);
        sb.append(">");

        sb.append(value);

        sb.append("</");
        sb.append(Key);
        sb.append(">");

        return sb;
    }
}
